package al.work.common.task;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.Semaphore;

/**
 * 任务线程池
 * @author JiuZh
 */
public class TaskThread {

    /**
     * 任务执行监听
     */
    public interface TaskRunningListener {
        boolean callback(ITaskRunnable runnable);
    }

    /**
     * list任务
     */
    private final List<ITaskRunnable> list_task_ = new ArrayList<>();

    /**
     * 信号量
     */
    private final Semaphore semaphore_ = new Semaphore(0);

    /**
     * 运行
     */
    private volatile boolean running_ = false;

    /**
     * 处理线程
     */
    private Vector<Thread> thread_list_ = null;

    /**
     * 最大等待任务数量
     */
    private int max_wait_task_ = -1;

    /**
     * 执行前
     */
    private TaskRunningListener before_listener_ = null;

    /**
     * 执行后
     */
    private TaskRunningListener after_listener_ = null;

    /**
     * 添加任务
     * @param runnable 任务
     */
    public boolean addTask(ITaskRunnable runnable) {
        synchronized (list_task_) {
            if (list_task_.size() >= max_wait_task_) {
                return false;
            }
            list_task_.add(runnable);
        }

        semaphore_.release();
        return true;
    }

    public void initialize(int count, int maxWaitTask) {
        initialize(count, maxWaitTask, "task_thread");
    }

    public void initialize(int count, int maxWaitTask, String ident) {
        initialize(count, maxWaitTask, ident, null);
    }

    public void initialize(int count, int maxWaitTask, String ident, TaskRunningListener before) {
        initialize(count, maxWaitTask, ident, before, null);
    }

    /**
     * 初始化线程
     * @param count 线程数量
     * @param ident 线程名称标识
     */
    public void initialize(int count, int maxWaitTask, String ident, TaskRunningListener before, TaskRunningListener after) {
        max_wait_task_ = maxWaitTask;
        before_listener_ = before;
        after_listener_ = after;

        synchronized (semaphore_) {
            if (null != thread_list_) {
                return;
            }
            running_ = true;

            thread_list_ = new Vector<>(count);
            for (int i = 0;i < count; ++i) {
                Thread single = new Thread(this::running);
                single.setName(ident + ":" + i);
                single.start();
                thread_list_.add(single);
            }
        }
    }

    /**
     * 反初始化
     */
    public void unInitialize() {
        running_ = false;
        if (null != thread_list_) {
            for (int i = 0;i < thread_list_.size(); ++i) {
                addTask(null);
            }
            thread_list_.forEach(thread -> {
                try {
                    thread.join();
                } catch (Exception ignored) {
                }
            });
            thread_list_ = null;
        }
    }

    /**
     * 线程执行方法
     */
    private void running() {
        while(running_) {

            try{
                semaphore_.acquire();

                ITaskRunnable task;
                synchronized (list_task_) {
                    if (0 == list_task_.size()){
                        continue;
                    }

                    task = list_task_.get(0);
                    list_task_.remove(0);
                }
                if (null == task) {
                    continue;
                }

                if(null == before_listener_ || before_listener_.callback(task)) {
                    try{
                        task.run();
                    } catch (Exception ex1) {
                        ex1.printStackTrace();
                    }
                    if(null != after_listener_) {
                        after_listener_.callback(task);
                    }
                }
            } catch (Exception ex){
                ex.printStackTrace();
            }
        }
    }
}
